package com.tags.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.constant.RedisKey;
import com.common.context.UserContext;
import com.common.domain.po.Tags;
import com.common.domain.vo.TagsListVO;
import com.tags.mapper.TagsMapper;
import com.tags.service.TagsService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 标签服务实现类
 * 继承自ServiceImpl，实现TagsService接口
 */
@Service
@RequiredArgsConstructor
public class TagsServiceImpl extends ServiceImpl<TagsMapper, Tags> implements TagsService {

    // Redis模板，用于操作Redis缓存
    private final RedisTemplate redisTemplate;

    // 线程池任务执行器，用于异步执行任务
    private final ThreadPoolTaskExecutor taskExecutor;

    /**
     * 保存标签
     * 如果Redis中没有缓存，则从数据库中获取标签列表
     * 对于每个新标签，如果它不在现有的标签字符串中，则将其添加
     * 最后，将更新后的标签字符串保存回数据库，并删除Redis缓存
     *
     * @param tagsMap 包含标签信息的映射
     */
    @Override
    public void saveTags(Map<String, String> tagsMap) {
        String key = RedisKey.TAGS_LIST_KEY;
        Long size = redisTemplate.opsForList().size(key);
        List<Tags> list = new ArrayList<>();
        if (size == null || size == 0) {
            list = list();
        } else {
            list = redisTemplate.opsForList().range(key, 0, -1);
        }
        if (!list.isEmpty()) {
            String existingTags = list.get(0).getTags();
            StringBuilder tagsBuilder = new StringBuilder(existingTags);
            String[] tagsArray = tagsMap.get("tags").split(",");
            for (String tag : tagsArray) {
                tag = tag.trim();
                if (!tagsBuilder.toString().contains(tag)) {
                    if (tagsBuilder.length() > 0) {
                        tagsBuilder.append(",");
                    }
                    tagsBuilder.append(tag);
                }
            }
            String updatedTags = tagsBuilder.toString();
            lambdaUpdate().set(Tags::getTags, updatedTags).update();
            taskExecutor.execute(() -> redisTemplate.delete(key));
        }
    }

    /**
     * 列出标签
     * 如果Redis中没有缓存，则从数据库中获取标签列表，并将其存储到Redis中
     * 否则，直接从Redis缓存中获取标签列表
     *
     * @return 标签列表
     */
    @Override
    public List<TagsListVO> listTags() {
        System.out.println("UserContext.getCurrentId() = " + UserContext.getCurrentId());
        String key = RedisKey.TAGS_LIST_KEY;
        Long size = redisTemplate.opsForList().size(key);
        List<Tags> tagsList = new ArrayList<>();
        if (size == null || size == 0){
            List<Tags> tags = list();
            taskExecutor.execute(() -> redisTemplate.opsForList().rightPushAll(key, tags));
            tagsList = tags;
        }else {
            tagsList = redisTemplate.opsForList().range(key, 0, -1);
        }
        String tags = tagsList.get(0).getTags();
        String[] tagArray = tags.split(",");
        List<TagsListVO> tagsListVOList = new ArrayList<>();
        for (String tag : tagArray) {
            TagsListVO tagsListVO = new TagsListVO(tag, tag);
            tagsListVOList.add(tagsListVO);
        }
        return tagsListVOList;
    }

    /**
     * 移除标签
     * 从标签字符串中移除指定的标签，并将更新后的标签字符串保存回数据库
     * 同时，删除Redis缓存，以保持缓存的一致性
     *
     * @param tags 要移除的标签
     */
    @Override
    public void removeTags(String tags) {
        String key = RedisKey.TAGS_LIST_KEY;
        Long size = redisTemplate.opsForList().size(key);
        String dataTags = null;
        if (size == null || size == 0){
            dataTags = list().get(0).getTags();
        }else {
            Object obj = redisTemplate.opsForList().range(key, 0, -1).get(0);
            Tags tag = (Tags) obj;
            dataTags = tag.getTags();
        }
        String[] dataTagsArray = dataTags.split(",");
        List<String> collect = Arrays.stream(dataTagsArray).filter(s -> !s.contains(tags)).collect(Collectors.toList());
        String tagsResult = String.join(",", collect);
        lambdaUpdate().set(Tags::getTags, tagsResult).update();
        taskExecutor.execute(() -> redisTemplate.delete(key));
    }
}
